/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace MyPhotoIndex.Utilities
{
    public sealed class Win32Interop
    {
        #region General messages
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

        #endregion

        #region Drawing
        [DllImport("user32")]
        public static extern int ScrollDC(int hdc, int dx, int dy, ref RECT lprcScroll, ref RECT lprcClip, int hrgnUpdate, ref RECT lprcUpdate);

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
        #endregion

        public const int WM_PAINT = 0x000F;
        public const int WM_NCCALCSIZE = 0x0083;
        public const int WM_NCPAINT = 0x0085;
        public const int WM_NCHITTEST = 0x84;
        public const int WM_SIZE = 0x05;
        public const int WM_SETCURSOR = 32;

        [StructLayout(LayoutKind.Sequential)]
        public struct PAINTSTRUCT
        {
            public IntPtr hdc;
            public bool fErase;
            public RECT rcPaint;
            public bool fRestore;
            public bool fIncUpdate;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public byte[] rgbReserved;
        }

        [DllImport("user32")]
        public static extern IntPtr BeginPaint(IntPtr hwnd, ref PAINTSTRUCT lpPaint);

        [DllImport("user32")]
        public static extern bool EndPaint(IntPtr hwnd, ref PAINTSTRUCT lpPaint);

        [DllImport("user32.dll", EntryPoint = "GetWindowDC")]
        public static extern IntPtr GetWindowDC(IntPtr ptr);

        [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);


        [StructLayout(LayoutKind.Sequential)]
        // This is the default layout for a structure
        public struct NCCALCSIZE_PARAMS
        {
            // Can't use an array here so simulate one
            public RECT rect0, rect1, rect2;
            public IntPtr lppos;
        }

        #region Files DragDrop
        [DllImport("shell32.dll")]
        public static extern void DragAcceptFiles(IntPtr hwnd, bool accept);

        [DllImport("shell32.dll")]
        public static extern int DragQueryFile(IntPtr hdrop, int ifile, StringBuilder fname, int fnsize);

        [DllImport("shell32.dll")]
        public static extern void DragFinish(IntPtr hdrop);

        public const int WM_DROPFILES = 0x233;
        #endregion

        #region Processes
        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool SetHandleInformation(IntPtr hObject, uint dwMask, uint dwFlags);
        #endregion

        #region scrollBar
        [DllImport("user32.dll")]
        public static extern int ShowScrollBar(IntPtr hWnd, int wBar, int bshow);

        [DllImport("user32.dll")]
        public static extern int GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO ScrollInfo);

        [DllImport("user32.dll")]
        public static extern int SetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO ScrollInfo, bool redraw);


        public const int SB_HORZ = 0;
        public const int SB_VERT = 1;

        public const int WM_SCROLL = 276; // Horizontal scroll
        public const int WM_VSCROLL = 277; // Vertical scroll
        public const int SB_PAGETOP = 6; // Scrolls to the upper left

        public const int WM_MOUSEWHEEL = 522;
        public const int WM_HSCROLL = 0x0114;
        public const int SB_LINEUP = 0; // Scrolls one line up
        public const int SB_LINELEFT = 0;// Scrolls one cell left
        public const int SB_LINEDOWN = 1; // Scrolls one line down
        public const int SB_LINERIGHT = 1;// Scrolls one cell right
        public const int SB_PAGEUP = 2; // Scrolls one page up
        public const int SB_PAGELEFT = 2;// Scrolls one page left
        public const int SB_PAGEDOWN = 3; // Scrolls one page down
        public const int SB_PAGERIGTH = 3; // Scrolls one page right

        public const int SB_LEFT = 6; // Scrolls to the left
        public const int SB_PAGEBOTTOM = 7; // Scrolls to the upper right
        public const int SB_RIGHT = 7; // Scrolls to the right
        public const int SB_ENDSCROLL = 8; // Ends scroll

        public const int SIF_RANGE = 0x0001;
        public const int SIF_PAGE = 0x0002;
        public const int SIF_POS = 0x0004;
        public const int SIF_DISABLENOSCROLL = 0x0008;
        public const int SIF_TRACKPOS = 0x0010;
        public const int SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS);

        [StructLayout(LayoutKind.Sequential)]
        public struct SCROLLINFO
        {
            public int cbSize;
            public int fMask;
            public int nMin;
            public int nMax;
            public int nPage;
            public int nPos;
            public int nTrackPos;
        }
        #endregion

        #region TreeView
        [StructLayout(LayoutKind.Sequential)]
        public struct TVITEMEX
        {
            public int mask;
            public IntPtr hItem;
            public int state;
            public int stateMask;
            public IntPtr pszText;
            public int cchTextMax;
            public int iImage;
            public int iSelectedImage;
            public int cChildren;
            public IntPtr lParam;
            public int iIntegral;
        }

        public const int TVM_SETITEMHEIGHT = 0x111B;
        public const int TV_FIRST = 0x1100;
        public const int TVM_GETITEM = TV_FIRST + 62;
        public const int TVM_SETITEM = TV_FIRST + 63;
        public const int TVIF_INTEGRAL = 0x0080;
        #endregion

        #region System Parameters
        public const int SPI_SETDESKWALLPAPER = 20;
        public const int SPIF_UPDATEINIFILE = 0x01;
        public const int SPIF_SENDWININICHANGE = 0x02;

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);

        #endregion

        #region Windows
        [DllImport("user32.dll")]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
        public const int SW_SHOWNORMAL = 1;
        public const int SW_SHOWMAXIMIZED = 3;
        public const int SW_SHOWNOACTIVATE = 4;
        public const int SW_RESTORE = 9;

        public const int HWND_TOPMOST = -1;
        public const uint SWP_NOACTIVATE = 0x0010;

        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        public static extern bool SetWindowPos(
             int hWnd,           // window handle
             int hWndInsertAfter,    // placement-order handle
             int X,          // horizontal position
             int Y,          // vertical position
             int cx,         // width
             int cy,         // height
             uint uFlags);       // window positioning flags

        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        #endregion

        #region Web
        public struct Struct_INTERNET_PROXY_INFO
        {
            public int dwAccessType;
            public IntPtr proxy;
            public IntPtr proxyBypass;
        };

        [DllImport("wininet.dll", SetLastError = true)]
        public static extern bool InternetSetOption(IntPtr hInternet,
        int dwOption,
        IntPtr lpBuffer,
        int lpdwBufferLength);

        public const int INTERNET_OPTION_PROXY = 38;
        public const int INTERNET_OPEN_TYPE_PROXY = 3;
        #endregion


        public class ImageDragHelper
        {
            [DllImport("comctl32.dll")]
            public static extern bool InitCommonControls();

            [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
            public static extern bool ImageList_BeginDrag(
                IntPtr himlTrack, // Handler of the image list containing the image to drag
                int iTrack,       // Index of the image to drag 
                int dxHotspot,    // x-delta between mouse position and drag image
                int dyHotspot     // y-delta between mouse position and drag image
            );

            [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
            public static extern bool ImageList_DragMove(
                int x,   // X-coordinate (relative to the form,
                // not the treeview) at which to display the drag image.
                int y   // Y-coordinate (relative to the form,
                // not the treeview) at which to display the drag image.
            );

            [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
            public static extern void ImageList_EndDrag();

            [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
            public static extern bool ImageList_DragEnter(
                IntPtr hwndLock,  // Handle to the control that owns the drag image.
                int x,            // X-coordinate (relative to the treeview)
                // at which to display the drag image. 
                int y             // Y-coordinate (relative to the treeview)
                // at which to display the drag image. 
            );

            [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
            public static extern bool ImageList_DragLeave(
                IntPtr hwndLock  // Handle to the control that owns the drag image.
            );

            [DllImport("comctl32.dll", CharSet = CharSet.Auto)]
            public static extern bool ImageList_DragShowNolock(
                bool fShow       // False to hide, true to show the image
            );

            static ImageDragHelper()
            {
                InitCommonControls();
            }
        }

        public static void SetTreeViewItemHeight(TreeView treeView, TreeNode node, int factor)
        {
            if (OSUtils.GetOSInfo().StartsWith("Windows 7") == true)
            {
                return;// widows 7 handles the node height unexpectedly flickers slot, I mean a-lot)
            }

            Win32Interop.TVITEMEX item = new Win32Interop.TVITEMEX();
            item.hItem = node.Handle;
            item.iIntegral = factor;
            item.mask = Win32Interop.TVIF_INTEGRAL;

            IntPtr lparam = Marshal.AllocHGlobal(Marshal.SizeOf(item));
            Marshal.StructureToPtr(item, lparam, false);
            int res = Win32Interop.SendMessage(treeView.Handle, Win32Interop.TVM_SETITEM, IntPtr.Zero, lparam);
            Marshal.FreeHGlobal(lparam);
        }
    }
}
